/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://dylab.googlecode.com

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

#ifndef __dylab_ComModel_h__
#define __dylab_ComModel_h__

//===========================================================================================
#include <dylab/simobject/ISimObjectComponent.h>
#include <dylab/utils/thread/GuardedObject.h>
#include <dylab/utils/containers/HashObjContainer.h>
#include <dylab/utils/containers/ListObjContainer.h>
#include <dylab/utils/containers/VectorObjContainer.h>
#include <dylab/utils/containers/ListContainer.h>
#include <dylab/utils/geometry/TetrahedronGeometry.h>
#include <dylab/utils/geometry/TriangleGeometry3.h>
#include <dylab/utils/geometry/EdgeGeometry3.h>
#include <dylab/utils/EnumIterator.h>
#include <dylab/utils/BitFlags.h>
#include <dylab/utils/components/ComponentBase.h>
#include <dylab/utils/exceptions/ENotImplemented.h>

//===========================================================================================
namespace dylab {

    /** Model structure component type.
	@remarks
		This class defines an interface for the simulation object model structure component type.
		Model structure can be viewed from many perspectives,
		that are represented as interfaces, 
		which can be queried for support and retrieved.
		Components of this type are responsible for implementing the any number of model structure interfaces.
		However, technique and integrator components must be chosen accordingly,
		to use only the interfaces, that the current component implements.
    @warning 
		Never use pointers to the declared interfaces without 
		locking up the whole ComModelStructure::Instace object!
    */
    class DYLAB_EXPORT ComModelStructure  
		: public ISimObjectComponent
        , public ComponentBase<ComModelStructure>
    {
    public:
        /** This class defines the interface for mass points representation.
		*/
        class DYLAB_EXPORT IMassPoints
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IMassPoints>
            {
            public:
                ScopedShLock(const Instance * _modelGuard)
                    : Instance::ScopedShLock_InternalObj<IMassPoints>(_modelGuard)
                        { mInternalObjPtr = mObjectPtr->getMassPointsInterface(); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IMassPoints>
            {
            public:
                ScopedExLock(Instance * _modelGuard)
                    : Instance::ScopedExLock_InternalObj<IMassPoints>(_modelGuard)
                        { mInternalObjPtr = mObjectPtr->getMassPointsInterface(); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// This class represents one mass point.
            class DYLAB_EXPORT MassPoint
            {
            private:
                typedef BitFlags8 BitFlagsT;
            public:
                /// Mass point flag codes.
                enum flags_t
                {
                    F_BOUNDARY = 0,
                    F_FIXED
                };
                /// The type of mass point identification.
                typedef uint32_t id_t;
				//-----------------------------------------------------------------------------
				/// Mass point's state attributes.
				struct State
				{
					State()
							{ }
					State(const Vector3 & _pos, const Vector3 & _vel, const Vector3 & _force)
						: position(_pos), velocity(_vel), force(_force)
							{ }
					/// Current position
					Vector3 position;
			        /// Current mass point velocity vector
				    Vector3 velocity;   
		            /// Current mass point force vector
	                Vector3 force;
				};
				//-----------------------------------------------------------------------------
				/// Maximum number of mass point history records.
				enum
				{ MAX_HISTORY_SIZE = 4 };
				//-----------------------------------------------------------------------------
				/// Mass point's history
				class DYLAB_EXPORT HistoryStates
				{ 
				private:
					/// Number of histry states
					uint32_t mSize;
					/// History states
					State * mStates[MAX_HISTORY_SIZE];
				public:
					/// The constructor creates required number of state structures					
					/// and populates them with values of the current state.
					HistoryStates(uint32_t _size, const State & _currState);
					/// Destructor deletes all previously created states
					~HistoryStates();
					/// Stores the current state into the history shifting it one step back.
					void storeState(const State & _currState);
					/// Retrieves the state with the given index.
					inline State * getState(uint32_t _index)
							{ DYLAB_ASSERT(_index < mSize); return mStates[_index]; }
					/// Retrieves the state with the given index, const version.
					inline const State * getState(uint32_t _index) const
							{ DYLAB_ASSERT(_index < mSize); return mStates[_index]; }
					/// Returns the number available history of states.
					inline uint32_t getSize() const
							{ return mSize; }
				};
				//-----------------------------------------------------------------------------				
            protected:
                /// Mass point identification number
                id_t mId;
                /// Mass of the point
                real_t mMass;  
                /// Current mass point's flags
                BitFlagsT mFlags;
				/// Mass point's current state
				State mCurrState;
				/// Mass point's histroy
				HistoryStates * mHistoryStates;
            private:
                /// Default construction is not allowed.
                inline MassPoint()
                        { }
            public:
                inline MassPoint(id_t _id, const Vector3 & _pos = Vector3::ZERO, real_t _mass = Math::ZERO, BitFlagsT::data_t _flags = 0)
					: mId(_id), mMass(_mass), mFlags(_flags), mCurrState(_pos, Vector3::ZERO, Vector3::ZERO), 
					  mHistoryStates(NULL)
                        { }
                virtual ~MassPoint()
                        { if (mHistoryStates != NULL) delete mHistoryStates; }
                inline id_t getId() const
                        { return mId; }

                inline void setMass(real_t _mass)
                        { mMass = _mass; }
                inline real_t getMass() const
                        { return mMass; }
                
                inline BitFlagsT & flags()
                        { return mFlags; }
                inline const BitFlagsT & flags() const
                        { return mFlags; }

                /// Returns mass point's current state.
                inline State & currState()
                        { return mCurrState; }
                /// Returns mass point's current state, const version.
                inline const State & currState() const
                        { return mCurrState; }

				/// Reserve the specified minimal number of history states.
				void reserveHistoryStates(uint32_t _noStates);

				/// Stores the current state into the history, shifting all other history states one step back.
				inline void storeState()
						{ DYLAB_ASSERT(mHistoryStates != NULL); mHistoryStates->storeState(mCurrState); }

				/** Returns mass point's previous state with the given nubmer of steps back in history.
				@remarks History steps counting starts from 1.
				*/
				inline State & historyState(uint32_t _stepsBack)
						{ DYLAB_ASSERT(mHistoryStates != NULL); return *(mHistoryStates->getState(_stepsBack - 1)); }

				/** Returns mass point's previous state with the given nubmer of steps back in history, const version.
				@remarks History steps counting starts from 1.
				*/
				inline const State & historyState(uint32_t _stepsBack) const
						{ DYLAB_ASSERT(mHistoryStates != NULL); return *(mHistoryStates->getState(_stepsBack - 1)); }
			};
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT MassPointMap
                : public HashObjContainer<MassPoint::id_t, MassPoint>
            {
            public:
                MassPointMap(bool _objectOwner)
                    : HashObjContainer<MassPoint::id_t, MassPoint>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
			/**  Create the specified number of mass points.
			@param[in] _count
				Number of requested mass points that should be created.
			@returns
				ID of the first mass point.
				IDs of the next mass points increases on each step by one.
		    */
            virtual MassPoint::id_t createMassPoints(uint32_t _count) = 0;

			/** Returns mass point iterator.
		    */
            virtual MassPointMap::Iterator massPointIterator() = 0;

			/** Returns mass point iterator, const version.
		    */
            virtual MassPointMap::ConstIterator massPointIterator() const = 0;

			/** Returns mass point reader.
		    */
            virtual MassPointMap::Reader massPointReader() = 0;

			/** Returns mass point reader, const version.
		    */
            virtual const MassPointMap::Reader massPointReader() const = 0;

			/** Performs any necessary tasks to prepare the mass points for rendering.
		    */
            virtual void prepareForRendering() = 0;

			/** Returns ID of the mass point that lies nearest to the given location.
			@param[in] _pos
				The target location.
		    */
            virtual MassPoint::id_t getNearestMassPointId(const Vector3 & _pos) = 0;

		public:

			/** Ensures, that the mass points can hold 
				at least the specified number of history states.
			@param[in] _noStates
				The number of requested history states
		    */
			void reserveHistoryStates(uint32_t _noStates);

			/** Applies the magnet force on all mass points.
			@remarks
				The force is pointing toward the specified magnet,
				acts on all mass points in the given radius
				and is controlled by the coefficient and attenuation exponent.
			@param[in] _magnet
				Location of the magnet point.
			@param[in] _radius
				Radius defines the boundary of the magnet force effect.
			@param[in] _forceCoeff
				The magnet force coefficient.
			@param[in] _attenuationExp
				The manget force attenuation exponent.
		    */
			void applyPointMagnetForce(const Vector3 & _magnet, real_t _radius, 
				real_t _forceCoeff, real_t _attenuationExp);

			/** Applies the magnet force on all mass points.
			@remarks
				The force is pointing toward the specified magnet,
				acts on all mass points in the given radius
				and is controlled by the coefficient and attenuation exponent.
			@param[in] _massPointId
				Location of the magnet point defined using one of the mass points.
			@param[in] _radius
				Radius defines the boundary of the magnet force effect.
			@param[in] _forceCoeff
				The magnet force coefficient.
			@param[in] _attenuationExp
				The manget force attenuation exponent.
		    */
	        void applyPointMagnetForce(MassPoint::id_t _massPointId, real_t _radius, 
				real_t _forceCoeff, real_t _attenuationExp);
		};
        //-----------------------------------------------------------------------------

    public:
        /** This class defines the interface for tetrahedral volume representation.
		*/
        class DYLAB_EXPORT ITetrahedralVolume
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<ITetrahedralVolume>
            {
            public:
                ScopedShLock(const Instance * _modelGuard)
                    : Instance::ScopedShLock_InternalObj<ITetrahedralVolume>(_modelGuard)
                        { mInternalObjPtr = mObjectPtr->getTetrahedralVolumeInterface(); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<ITetrahedralVolume>
            {
            public:
                ScopedExLock(Instance * _modelGuard)
                    : Instance::ScopedExLock_InternalObj<ITetrahedralVolume>(_modelGuard)
                        { mInternalObjPtr = mObjectPtr->getTetrahedralVolumeInterface(); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// This class represents one tetrahedral mesh edge
            class DYLAB_EXPORT Edge
            {
            public:
                typedef uint32_t id_t;

            protected:
                id_t mId;
                IMassPoints::MassPoint * mMassPoints[EdgeGeometry3::V_COUNT];

            public:
                Edge()
                        { }
                Edge(id_t _id, IMassPoints::MassPoint * _mp0, IMassPoints::MassPoint * _mp1)
                    : mId(_id)
                        { 
                            mMassPoints[EdgeGeometry3::V_0] = _mp0, 
                            mMassPoints[EdgeGeometry3::V_1] = _mp1; 
                        }
                Edge(id_t _id, IMassPoints::MassPoint * (&_mp)[EdgeGeometry3::V_COUNT]) 
                    : mId(_id)
                        { 
                            for (EdgeGeometry3::VertexIdxIterator vertexIdx; vertexIdx.isValid(); vertexIdx++) 
                                mMassPoints[vertexIdx] = _mp[vertexIdx]; 
                        }
                virtual ~Edge()
                        { }
                id_t getId() const
                        { return mId; }
                IMassPoints::MassPoint * getMassPoint(EdgeGeometry3::vertexidx_t _vertexIdx)
                        { 
                            DYLAB_ASSERT(mMassPoints[_vertexIdx] != NULL);
                            return mMassPoints[_vertexIdx]; 
                        }
                const IMassPoints::MassPoint * getMassPoint(EdgeGeometry3::vertexidx_t _vertexIdx) const
                        { 
                            DYLAB_ASSERT(mMassPoints[_vertexIdx] != NULL);
                            return mMassPoints[_vertexIdx]; 
                        }
                EdgeGeometry3 getGeometry() const
                        { return EdgeGeometry3(getMassPoint(EdgeGeometry3::V_0)->currState().position, getMassPoint(EdgeGeometry3::V_1)->currState().position); }
            };
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT EdgeMap
                : public HashObjContainer<Edge::id_t, Edge>
            {
            public:
                EdgeMap(bool _objectOwner)
                    : HashObjContainer<Edge::id_t, Edge>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT EdgeList
                : public ListObjContainer<Edge>
            {
            public:
                EdgeList(bool _objectOwner)
                    : ListObjContainer<Edge>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
            /// This class represents the tetrahedral mesh triangle
            class DYLAB_EXPORT Triangle
            {
            public:
                typedef uint32_t id_t;

            protected:
                id_t mId;
                IMassPoints::MassPoint * mMassPoints[TriangleGeometry3::V_COUNT];
                bool mIsBoundary;

            public:
                Triangle()
                        { }
                Triangle(id_t _id, IMassPoints::MassPoint * _mp0, IMassPoints::MassPoint * _mp1, 
					IMassPoints::MassPoint * _mp2, bool _boundary)
                    : mId(_id), mIsBoundary(_boundary)
                        { 
                            mMassPoints[TriangleGeometry3::V_0] = _mp0, 
                            mMassPoints[TriangleGeometry3::V_1] = _mp1, 
                            mMassPoints[TriangleGeometry3::V_2] = _mp2; 
                        }
                Triangle(id_t _id, IMassPoints::MassPoint * (&_mp)[TriangleGeometry3::V_COUNT]) 
                    : mId(_id)
                        { 
                            for (TriangleGeometry3::VertexIdxIterator vertexIdx; vertexIdx.isValid(); vertexIdx++) 
                                mMassPoints[vertexIdx] = _mp[vertexIdx]; 
                        }
                virtual ~Triangle()
                        { }
                id_t getId() const
                        { return mId; }
                IMassPoints::MassPoint * getMassPoint(TriangleGeometry3::vertexidx_t _vertexIdx)
                        { 
                            DYLAB_ASSERT(mMassPoints[_vertexIdx] != NULL);
                            return mMassPoints[_vertexIdx]; 
                        }
                const IMassPoints::MassPoint * getMassPoint(TriangleGeometry3::vertexidx_t _vertexIdx) const
                        { 
                            DYLAB_ASSERT(mMassPoints[_vertexIdx] != NULL);
                            return mMassPoints[_vertexIdx]; 
                        }
                bool isBoundary() const
                        { return mIsBoundary; }
                void setBoundary(bool _boundary)
                        { mIsBoundary = _boundary; }
                TriangleGeometry3 getGeometry() const
                        { 
                            return TriangleGeometry3(getMassPoint(TriangleGeometry3::V_0)->currState().position, 
                                                     getMassPoint(TriangleGeometry3::V_1)->currState().position, 
                                                     getMassPoint(TriangleGeometry3::V_2)->currState().position); 
                        }
                virtual Edge::id_t getEdgeID(TriangleGeometry3::edgeidx_t _edgeIdx) const
                        { DYLAB_NOT_IMPLEMENTED(); return 0; }
            };            
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT TriangleMap
                : public HashObjContainer<Triangle::id_t, Triangle>
            {
            public:
                TriangleMap(bool _objectOwner)
                    : HashObjContainer<Triangle::id_t, Triangle>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT TriangleList
                : public ListObjContainer<Triangle>
            {
            public:
                TriangleList(bool _objectOwner)
                    : ListObjContainer<Triangle>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------


        public:
            /// This class represents a tetrahedron
            class DYLAB_EXPORT Tetrahedron
            {
            public:
                typedef uint32_t id_t;

            protected:

                id_t mId;
                IMassPoints::MassPoint * mMassPoints[TetrahedronGeometry::V_COUNT];

            public:
                Tetrahedron()
                        { }
                Tetrahedron(id_t _id, IMassPoints::MassPoint * _mp0, IMassPoints::MassPoint * _mp1, 
					IMassPoints::MassPoint * _mp2, IMassPoints::MassPoint * _mp3) 
					: mId(_id)
                        { 
                            mMassPoints[TetrahedronGeometry::V_0] = _mp0, 
                            mMassPoints[TetrahedronGeometry::V_1] = _mp1, 
                            mMassPoints[TetrahedronGeometry::V_2] = _mp2, 
                            mMassPoints[TetrahedronGeometry::V_3] = _mp3; 
                        }
                Tetrahedron(id_t _id, IMassPoints::MassPoint * (&_mp)[TetrahedronGeometry::V_COUNT]) 
					: mId(_id)
                        { 
                            for (TetrahedronGeometry::VertexIdxIterator vertexIdx; vertexIdx.isValid(); vertexIdx++) 
                                mMassPoints[vertexIdx] = _mp[vertexIdx]; 
                        }
                virtual ~Tetrahedron()
                        { }
                id_t getId() const
                        { return mId; }
                IMassPoints::MassPoint * getMassPoint(TetrahedronGeometry::vertexidx_t _vertexIdx)
                        { 
                            DYLAB_ASSERT(mMassPoints[_vertexIdx] != NULL);
                            return mMassPoints[_vertexIdx]; 
                        }
                const IMassPoints::MassPoint * getMassPoint(TetrahedronGeometry::vertexidx_t _vertexIdx) const
                        { 
                            DYLAB_ASSERT(mMassPoints[_vertexIdx] != NULL);
                            return mMassPoints[_vertexIdx]; 
                        }
                TetrahedronGeometry getGeometry() const
                        { 
                            return TetrahedronGeometry(getMassPoint(TetrahedronGeometry::V_0)->currState().position, 
                                                       getMassPoint(TetrahedronGeometry::V_1)->currState().position, 
                                                       getMassPoint(TetrahedronGeometry::V_2)->currState().position, 
                                                       getMassPoint(TetrahedronGeometry::V_3)->currState().position); 
                        }
                /// Tests, if mass point id is part of the tetrahedron.
                bool containsMassPointId(IMassPoints::MassPoint::id_t _mpId)
                        {
                            for (TetrahedronGeometry::VertexIdxIterator vertexIdx; vertexIdx.isValid(); vertexIdx++)
                                if (mMassPoints[vertexIdx]->getId() == _mpId)
                                    return true;
                            return false;
                        }
                virtual Edge::id_t getEdgeID(TetrahedronGeometry::edgeidx_t _edgeIdx) const
                        { DYLAB_NOT_IMPLEMENTED(); return 0; }
                virtual Triangle::id_t getTriangleID(TetrahedronGeometry::faceidx_t _faceIdx) const
                        { DYLAB_NOT_IMPLEMENTED(); return 0; }
            };
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT TetrahedronMap
                : public HashObjContainer<Tetrahedron::id_t, Tetrahedron>
            {
            public:
                TetrahedronMap(bool _objectOwner)
                    : HashObjContainer<Tetrahedron::id_t, Tetrahedron>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------

        public:

			/** Creates a new tetrahedron and returns its ID.
			@remarks
				The new tetrahedron is specified by its 4 mass points
				identified by the 4 given IDs.
			@param[in] _mp1
				The ID of the first tetrahedron's mass point.
			@param[in] _mp2
				The ID of the second tetrahedron's mass point.
			@param[in] _mp3
				The ID of the third tetrahedron's mass point.
			@param[in] _mp4
				The ID of the fourth tetrahedron's mass point.
			@returns
				The ID of the newly created tetrahedron.
			*/
			virtual Tetrahedron::id_t createTetrahedron(IMassPoints::MassPoint::id_t _mp1, IMassPoints::MassPoint::id_t _mp2, 
				IMassPoints::MassPoint::id_t _mp3, IMassPoints::MassPoint::id_t _mp4) = 0;

			/** Destroys an existing tetrahedron.
			@param[in] _tetraID
				The ID of tetrahedron that should be destroyed.
		    */
            virtual void destroyTetrahedron(Tetrahedron::id_t _tetraID) = 0;

            /** Subdivides a tetrahedron by an inner point.
			@remarks
				Creates 4 new tetrahedra formed by the specified point and the corresponding opposite 3 points,
				and then destroys the original tetrahedron.
            @attention
				The point should not lie on any face or edge of the tetrahedron.
			@param[in] _tetraID
				The ID of the tetrahedron that should be subdivided.
			@param[in] _point
				The Point that subdivides the tetrahedron.
            */
            virtual void subdivideTetrahedron(Tetrahedron::id_t _tetraID, const Vector3 & _point) = 0;

			/** 
		    */
            virtual void subdivideEdge(Edge::id_t _edgeID, const Vector3 & _point) = 0;

			/**  
		    */
            virtual void subdivideTriangle(Triangle::id_t _triID, const Vector3 & _point) = 0;
			/**  
		    */
            virtual void collapseEdge(Edge::id_t _edgeID) = 0;
			/**  
		    */
            virtual EdgeMap::Iterator edgeIterator() = 0;
			/**  
		    */
            virtual EdgeMap::ConstIterator edgeIterator() const = 0;
			/**  
		    */
            virtual EdgeMap::Reader edgeReader() = 0;
			/**  
		    */
            virtual const EdgeMap::Reader edgeReader() const = 0;
			/**  
		    */
            virtual TriangleMap::Iterator triangleIterator() = 0;
			/**  
		    */
            virtual TriangleMap::ConstIterator triangleIterator() const = 0;
			/**  
		    */
            virtual TriangleMap::Reader triangleReader() = 0;
			/**  
		    */
            virtual const TriangleMap::Reader triangleReader() const = 0;
			/**  
		    */
            virtual TetrahedronMap::Iterator tetrahedronIterator() = 0;
			/**  
		    */
            virtual TetrahedronMap::ConstIterator tetrahedronIterator() const = 0;
			/**  
		    */
            virtual TetrahedronMap::Reader tetrahedronReader() = 0;
			/**  
		    */
            virtual const TetrahedronMap::Reader tetrahedronReader() const = 0;
			/**  
		    */
            virtual void prepareForRendering() = 0;

		public:

            /** Fills the specified cube with with 5 tetrahedrons.
            @remarks 
				Cube is defined by 2 face squares, one ordered CCW and the other CW.
            */
            void generateCubeSection(IMassPoints::MassPoint::id_t _mp1, IMassPoints::MassPoint::id_t _mp2, 
				IMassPoints::MassPoint::id_t _mp3, IMassPoints::MassPoint::id_t _mp4, IMassPoints::MassPoint::id_t _mp5, 
				IMassPoints::MassPoint::id_t _mp6, IMassPoints::MassPoint::id_t _mp7, IMassPoints::MassPoint::id_t _mp8);
        };
        //-----------------------------------------------------------------------------

    public:
		/** This class defines the interface for the boundary mesh representation.
		*/
        class DYLAB_EXPORT IBoundaryMesh
        {
        public:
            /// Shared scope lock with direct interface access.
            class DYLAB_EXPORT ScopedShLock
                : public Instance::ScopedShLock_InternalObj<IBoundaryMesh>
            {
            public:
                ScopedShLock(const Instance * _modelGuard)
                    : Instance::ScopedShLock_InternalObj<IBoundaryMesh>(_modelGuard)
                        { mInternalObjPtr = mObjectPtr->getBoundaryMeshInterface(); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// Exclussive scope lock with direct interface access.
            class DYLAB_EXPORT ScopedExLock
                : public Instance::ScopedExLock_InternalObj<IBoundaryMesh>
            {
            public:
                ScopedExLock(Instance * _modelGuard)
                    : Instance::ScopedExLock_InternalObj<IBoundaryMesh>(_modelGuard)
                        { mInternalObjPtr = mObjectPtr->getBoundaryMeshInterface(); }
            };
            //-----------------------------------------------------------------------------

        public:
            /// This class represents a boundary mesh vertex.
            class DYLAB_EXPORT Vertex
            {
            protected:
                uint32_t mIndex;
                Vector3	 mPosition;
                Vector3  mNormal;
                real_t   mTextureU;
                real_t   mTextureV;
                uint32_t mFaceNormalCounter;

            private:
                /// Non-initialized construction is not allowed.
                Vertex()
                        { }
            public:
                Vertex(uint32_t _index, const Vector3 & _position, const Vector3 & _normal = Vector3::ZERO, real_t _u = DYLAB_R(0), real_t _v = DYLAB_R(0))
                    : mIndex(_index), mPosition(_position), mNormal(_normal), mTextureU(_u), mTextureV(_v)
                        { }
                inline uint32_t getIndex() const
                        { return mIndex; }

                inline Vector3 & position()
                        { return mPosition; }
                inline const Vector3 & position() const
                        { return mPosition; }

                inline Vector3 & normal()
                        { return mNormal; }
                inline const Vector3 & normal() const
                        { return mNormal; }
                
                void setTextureU(real_t _u)
                        { mTextureU = _u; }                
                real_t getTextureU() const
                        { return mTextureU; }
                
                void setTextureV(real_t _v)
                        { mTextureV = _v; }                
                real_t getTextureV() const
                        { return mTextureV; }

                void beginNormalCalculation()
                        { 
                            mNormal = Vector3::ZERO; 
                            mFaceNormalCounter = 0; 
                        }               
                void addFaceNormal(const Vector3 & normal)
                        { 
                            mNormal += normal; 
                            mFaceNormalCounter++; 
                        }                
                void endNormalCalculation()
                        { 
                            mNormal /= static_cast<real_t>(mFaceNormalCounter); 
                            mNormal.normalise(); 
                        }
            };
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT VertexArray
                : public VectorObjContainer<Vertex>
            {
            public:
                VertexArray(bool _objectOwner)
                    : VectorObjContainer<Vertex>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
            /// This class represents a boundary mesh face.
            class DYLAB_EXPORT Face
            {
            public:
                typedef uint32_t id_t;

            protected:                
                Vertex * mVertices[TriangleGeometry3::V_COUNT];                
                Vector3  mNormal;

            private:
                /// Non-initialized construction is not allowed.
                Face()
                        { }
            public:                
                Face(Vertex * _v0, Vertex * _v1, Vertex * _v2, const Vector3 & _normal = Vector3::ZERO)
                    : mNormal(_normal)
                        { mVertices[TriangleGeometry3::V_0] = _v0, mVertices[TriangleGeometry3::V_1] = _v1, mVertices[TriangleGeometry3::V_2] = _v2; }                
                Face(Vertex * (&_vertices)[TriangleGeometry3::V_COUNT], const Vector3 & _normal = Vector3::ZERO)
                    : mNormal(_normal)
                        { 
                            for (TriangleGeometry3::VertexIdxIterator vertexIdx; vertexIdx.isValid(); vertexIdx++) 
                                mVertices[vertexIdx] = _vertices[vertexIdx]; 
                        }
                
                Vertex * vertex(TriangleGeometry3::vertexidx_t _vertexIdx)
                        { return mVertices[_vertexIdx]; }                
                const Vertex * vertex(TriangleGeometry3::vertexidx_t _vertexIdx) const
                        { return mVertices[_vertexIdx]; } 
                
                Vector3 & normal()
                        { return mNormal; }                
                const Vector3 & normal() const
                        { return mNormal; }
                
                uint32_t getVertexIndex(TriangleGeometry3::vertexidx_t _vertexIdx) const
                        { return mVertices[_vertexIdx]->getIndex(); }                

                TriangleGeometry3 getGeometry() const
                        { return TriangleGeometry3(mVertices[TriangleGeometry3::V_0]->position(), 
                                                   mVertices[TriangleGeometry3::V_1]->position(), 
                                                   mVertices[TriangleGeometry3::V_2]->position()); 
						} 

                void updateNormal()
                        { mNormal = getGeometry().computeNormal(); }                
                void distributeNormal()
                        { 
                            for (TriangleGeometry3::VertexIdxIterator vertexIdx; vertexIdx.isValid(); vertexIdx++) 
                                mVertices[vertexIdx]->addFaceNormal(mNormal); 
                        }
            };
            //-----------------------------------------------------------------------------

        public:
            class DYLAB_EXPORT FaceMap
                : public HashObjContainer<Face::id_t, Face>
            {
            public:
                FaceMap(bool _objectOwner)
                    : HashObjContainer<Face::id_t, Face>(_objectOwner)
                        { }
            };
            //-----------------------------------------------------------------------------

        public:
			/**  
		    */
            virtual void generateFromMassPoints() = 0;
			/**         
             */
            virtual void generateFromTetrahedralVolume() = 0;
			/**  
		    */
            virtual uint32_t createVertex(const Vector3 & _position, const Vector3 & _normal, real_t _u, real_t _v) = 0;
			/**  
		    */
            virtual Face::id_t createFace(uint32_t  _v0, uint32_t  _v1, uint32_t _v2) = 0;
			/**  
		    */
            virtual VertexArray::Iterator vertexIterator() = 0;
			/**  
		    */
            virtual VertexArray::ConstIterator vertexIterator() const = 0;
			/**  
		    */
            virtual VertexArray::Reader vertexReader() = 0;
			/**  
		    */
            virtual const VertexArray::Reader vertexReader() const = 0;
			/**  
		    */
            virtual FaceMap::Iterator faceIterator() = 0;
			/**  
		    */
            virtual FaceMap::ConstIterator faceIterator() const = 0;
			/**  
		    */
            virtual FaceMap::Reader faceReader() = 0;
			/**  
		    */
            virtual const FaceMap::Reader faceReader() const = 0;
			/**  
		    */
            virtual void prepareForRendering() = 0;
        };
        //-----------------------------------------------------------------------------

    public:
        ComModelStructure(const String & _componentName);

		/** Loads the model structure using the appropriate structure loader component.
		@remarks
			Loads the model structure with the data in the given property tree,
			which also contains the name of the model structure loader component.
		@param[in] _pt
			The property tree holding the data for this model structure.
		*/
		virtual void loadFromPropertyTree(const PropertyTree & _pt);

        /** The component should translate the whole model structure according to the given translate vector.
		@param[in] _trans
			The translate vector.
        */
        virtual void translate(const Vector3 & _trans) = 0;

        /** The component should rotate the whole model structure according to the given axis and angle.
		@param[in] _axis
			The rotation axis.
		@param[in] _radians
			The rotation angle in radians.
        */
        virtual void rotate(const Vector3 & _axis, real_t _radians) = 0;

        /** The component should scale the whole model structure according to the given scale vector.
		@param[in] _scale
			The scale vector.
        */
        virtual void scale(const Vector3 & _scale) = 0;

        /** The component should returns true, if it supports the IMassPoints interface.
        */
        virtual bool isMassPointsInterfaceSupported() = 0;

        /** Returns the pointer to an object implementing the IMassPoints interface.
         */
        virtual IMassPoints * getMassPointsInterface() = 0;

        /** Returns the pointer to an object implementing the IMassPoints interface, const version.
         */
        virtual const IMassPoints * getMassPointsInterface() const = 0;

        /** The component should returns true, if it supports the ITetrahedralVolume interface.
        */
        virtual bool isTetrahedralVolumeInterfaceSupported() = 0;

        /** Returns the pointer to an object implementing the ITetrahedralVolume interface.
         */
        virtual ITetrahedralVolume * getTetrahedralVolumeInterface() = 0;

        /** Returns the pointer to an object implementing the ITetrahedralVolume interface, const version.
         */
        virtual const ITetrahedralVolume * getTetrahedralVolumeInterface() const = 0;

        /** The component should returns true, if it supports the IBoundaryMesh interface.
        */
        virtual bool isBoundaryMeshInterfaceSupported() = 0;

        /** Returns the pointer to an object implementing the IBoundaryMesh interface.
         */
        virtual IBoundaryMesh * getBoundaryMeshInterface() = 0;

        /** Returns the pointer to an object implementing the IBoundaryMesh interface, const version.
         */
        virtual const IBoundaryMesh * getBoundaryMeshInterface() const = 0;
    };

    //===========================================================================================    
	inline std::ostream & operator << (std::ostream & _os, const ComModelStructure::IMassPoints::MassPoint::State & _o)
            { return _os << String::fmt("pos(%1%) vel(%2%) force(%3%)", _o.position, _o.velocity, _o.force); }
}
//===========================================================================================
#endif // __dylab_ComModel_h__
